#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <cassert>

namespace bitlog {

#define BUFFER_DEFAULT_SIZE (1*1024*1024)  // 定义默认缓冲区大小为1MB
#define BUFFER_INCREMENT_SIZE (1*1024*1024)  // 定义缓冲区每次扩展的大小为1MB
#define BUFFER_THRESHOLD_SIZE (10*1024*1024)  // 定义缓冲区扩展阈值为10MB

/// @brief 缓冲区类，用于存储和管理日志或其他数据
class Buffer {
    public:
        /// @brief 构造函数，初始化缓冲区
        Buffer(): 
        _reader_idx(0), 
        _writer_idx(0), 
        _v(BUFFER_DEFAULT_SIZE) {}

        /// @brief 检查缓冲区是否为空
        /// @return 如果读取指针和写入指针相同，返回 true 表示缓冲区为空
        bool empty() { 
            return _reader_idx == _writer_idx; 
        }

        /// @brief 获取可读数据的大小
        /// @return 返回可读数据的字节数
        size_t readAbleSize() { 
            return _writer_idx - _reader_idx; 
        }

        /// @brief 获取可写入的空间大小
        /// @return 返回可写入空间的字节数
        size_t writeAbleSize() { 
            return _v.size() - _writer_idx; 
        }

        /// @brief 重置缓冲区，将读写指针都置为0
        void reset() { 
            _reader_idx = _writer_idx = 0; 
        }

        /// @brief 交换两个缓冲区的数据
        /// @param buf 要交换的另一个缓冲区对象
        void swap(Buffer &buf) {
            _v.swap(buf._v);  // 交换内部存储向量
            std::swap(_reader_idx, buf._reader_idx);  // 交换读取指针
            std::swap(_writer_idx, buf._writer_idx);  // 交换写入指针
        }

        /// @brief 向缓冲区推入数据
        /// @param data 要写入的数据指针
        /// @param len 数据的长度
        void push(const char *data, size_t len) {
            assert(len <= writeAbleSize());  // 确保写入的数据不会超过可写空间
            ensureEnoughSpace(len);  // 确保有足够的空间写入数据
            std::copy(data, data + len, &_v[_writer_idx]);  // 将数据复制到缓冲区中
            _writer_idx += len;  // 更新写入指针
        }

        /// @brief 获取缓冲区中当前可读数据的起始地址
        /// @return 返回指向可读数据的指针
        const char* begin() { 
            return &_v[_reader_idx];
        }

        /// @brief 从缓冲区中移除一定长度的数据
        /// @param len 要移除的数据长度
        void pop(size_t len) {
            _reader_idx += len;  // 更新读取指针，移除数据
            assert(_reader_idx <= _writer_idx);  // 确保读取指针不会超过写入指针
        }

    protected:
        /// @brief 确保缓冲区有足够的空间来写入数据
        /// @param len 需要写入的数据长度
        void ensureEnoughSpace(size_t len) {
            if (len <= writeAbleSize()) {
                return;  // 如果当前可写空间足够，则不需要扩展
            }

            size_t new_capacity;
            if (_v.size() < BUFFER_THRESHOLD_SIZE){
                new_capacity = _v.size() * 2 + len;  // 如果当前大小小于阈值，倍增扩展
            }else{
                new_capacity = _v.size() + BUFFER_INCREMENT_SIZE + len;  // 否则每次只扩展1MB
            }
            _v.resize(new_capacity);  // 调整缓冲区大小
        }

    private:
        size_t _reader_idx;  // 读取指针，指示可读数据的起始位置
        size_t _writer_idx;  // 写入指针，指示可写数据的起始位置
        std::vector<char> _v;  // 用于存储数据的缓冲区（字符向量）
};

}
